/*     */ package com.zimbra.cs.servlet;
/*     */ 
/*     */ import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
/*     */ import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap.Builder;
/*     */ import com.zimbra.common.localconfig.KnownKey;
/*     */ import com.zimbra.common.localconfig.LC;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.AuthToken;
/*     */ import com.zimbra.cs.service.AuthProvider;
/*     */ import com.zimbra.cs.servlet.util.AuthUtil;
/*     */ import java.io.IOException;
/*     */ import java.util.concurrent.Semaphore;
/*     */ import java.util.concurrent.TimeUnit;
/*     */ import javax.servlet.Filter;
/*     */ import javax.servlet.FilterChain;
/*     */ import javax.servlet.FilterConfig;
/*     */ import javax.servlet.ServletException;
/*     */ import javax.servlet.ServletRequest;
/*     */ import javax.servlet.ServletResponse;
/*     */ import javax.servlet.http.HttpServletRequest;
/*     */ import javax.servlet.http.HttpServletResponse;
/*     */ import org.eclipse.jetty.continuation.Continuation;
/*     */ import org.eclipse.jetty.continuation.ContinuationSupport;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class ZimbraQoSFilter
/*     */   implements Filter
/*     */ {
/*     */   static final int DEFAULT_WAIT_MS = 50;
/*     */   static final long DEFAULT_SUSPEND_MS = 1000L;
/*     */   static final String MAX_WAIT_INIT_PARAM = "waitMs";
/*     */   static final String SUSPEND_INIT_PARAM = "suspendMs";
/*     */   private long waitMs;
/*     */   private long suspendMs;
/*  65 */   private ConcurrentLinkedHashMap<String, Semaphore> passes = new ConcurrentLinkedHashMap.Builder().maximumWeightedCapacity(2000L).build();
/*     */   
/*     */   public static String extractUserId(ServletRequest request)
/*     */   {
/*     */     try {
/*  70 */       if ((request instanceof HttpServletRequest)) {
/*  71 */         HttpServletRequest req = (HttpServletRequest)request;
/*  72 */         boolean isAdminRequest = AuthUtil.isAdminRequest(req);
/*  73 */         AuthToken at = AuthProvider.getAuthToken(req, isAdminRequest);
/*  74 */         if (at != null) {
/*  75 */           return at.getAccountId();
/*     */         }
/*  77 */         String auth = req.getHeader("Authorization");
/*  78 */         if (auth != null) {
/*  79 */           return auth;
/*     */         }
/*     */       }
/*     */     }
/*     */     catch (Exception e) {
/*  84 */       ZimbraLog.misc.debug("error while extracting authtoken", e);
/*     */     }
/*  86 */     return null;
/*     */   }
/*     */   
/*     */   public void init(FilterConfig filterConfig) {
/*  90 */     this.waitMs = 50L;
/*  91 */     if (filterConfig.getInitParameter("waitMs") != null) {
/*  92 */       this.waitMs = Integer.parseInt(filterConfig.getInitParameter("waitMs"));
/*     */     }
/*     */     
/*  95 */     this.suspendMs = 1000L;
/*  96 */     if (filterConfig.getInitParameter("suspendMs") != null) {
/*  97 */       this.suspendMs = Integer.parseInt(filterConfig.getInitParameter("suspendMs"));
/*     */     }
/*     */   }
/*     */   
/*     */   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
/*     */   {
/*     */     try {
/* 104 */       String user = extractUserId(request);
/* 105 */       int max = LC.servlet_max_concurrent_http_requests_per_account.intValue();
/* 106 */       if ((user == null) || (max <= 0)) {
/* 107 */         chain.doFilter(request, response);
/* 108 */         return;
/*     */       }
/* 110 */       Semaphore pass = (Semaphore)this.passes.putIfAbsent(user, new Semaphore(max, true));
/* 111 */       if (pass == null) {
/* 112 */         pass = (Semaphore)this.passes.get(user);
/*     */       }
/* 114 */       if (pass.tryAcquire(this.waitMs, TimeUnit.MILLISECONDS)) {
/*     */         try {
/* 116 */           chain.doFilter(request, response);
/*     */         } finally {
/* 118 */           pass.release();
/*     */         }
/*     */       } else {
/* 121 */         Continuation continuation = ContinuationSupport.getContinuation(request);
/* 122 */         HttpServletRequest hreq = (HttpServletRequest)request;
/* 123 */         ZimbraServlet.addRemoteIpToLoggingContext(hreq);
/* 124 */         ZimbraServlet.addUAToLoggingContext(hreq);
/* 125 */         ZimbraLog.misc.warn("Exceeded the max requests limit. Suspending " + continuation);
/* 126 */         ZimbraLog.clearContext();
/* 127 */         continuation.setTimeout(this.suspendMs);
/* 128 */         continuation.suspend();
/* 129 */         return;
/*     */       }
/*     */     } catch (InterruptedException e) {
/* 132 */       ((HttpServletResponse)response).sendError(503);
/* 133 */       return;
/*     */     }
/*     */   }
/*     */   
/*     */   public void destroy() {}
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/servlet/ZimbraQoSFilter.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */